#include "vroute.hpp"
#include "logger.hpp"

vroute* vroute::_instance = NULL;

vroute* vroute::getInstance(){
	debug_enter();
	if(_instance == NULL){
		debug_record(logger::LEVEL_INFO, "construct the vroute adapter  class");
		_instance = new vroute();
		if(_instance->getState() != INS_STATE_OK){
			debug_record(logger::LEVEL_ERROR, "get instance of vroute cpp failed");
			releaseInstance();
		}
	}
	debug_leave();
	return _instance;
}

void vroute::releaseInstance(){
	debug_enter();
	if(_instance != NULL){
		delete _instance;
		_instance = NULL;
		logger::releaseInstance();
	}
	debug_leave();
}

///call port manager getInstance
vroute::vroute(){
	debug_enter();
	mPortManager = TransContentPortMgr::getInstance();
	mState = mPortManager==NULL ? INS_STATE_ERROR : INS_STATE_OK;
	debug_leave();
}

vroute::~vroute(){
	debug_enter();
	TransContentPortMgr::releaseInstance();
	mPortManager = NULL;
	mState = INS_STATE_ERROR;
	debug_leave();
}

int vroute::start(){
	log_info("start the client");
	return mState;
}

int vroute::stop(){
	debug_enter();
	log_info("stop the client");
	debug_leave();
	return E_TRANC_SUCESS;
}

int vroute::getState(){
	return mState;
}

///////////////////////////////////////////////////////////
///Notice: because the every function has a sync method and invalidate to write code twice, just do the details
///in the port manager
///////////////////////////////////////////////////////////
vroute_t vroute::bind(int port, int timeout){	
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}
	return mPortManager->bind(port, timeout, NULL);
}

int vroute::bind_sync(int port, bindSyncCallback bscb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}
	return mPortManager->bind(port, -1, bscb);
}


int vroute::listen(vroute_t vid, int count){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}
	return mPortManager->listen(vid, count);
}


int vroute::accept(vroute_t vid, int timeout){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}
	return mPortManager->accept(vid, timeout, NULL);
}


int vroute::accept_sync(vroute_t vid, acceptSyncCallback ascb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}
	return mPortManager->accept(vid, -1, ascb);
}

int vroute::receive(vroute_t vid, int flag, void* buffer, int bufferLen, int timeout){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}
	return mPortManager->receive(vid, flag, buffer, bufferLen, timeout, NULL);
}

int vroute::receive_sync(vroute_t vid, recvSyncCallback rscb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}
	return mPortManager->receive(vid, 0, NULL, 0, -1, rscb);
}

int vroute::send(vroute_t vid, int flag, const void* buffer, int bufferLen, int timeout){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}
	return mPortManager->send(vid, flag, buffer, bufferLen, timeout, NULL);
}

int vroute::send_sync(vroute_t vid, int flag, const void* buffer, int bufferLen, sendSyncCallback sscb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}
	return mPortManager->send(vid, flag, buffer, bufferLen, -1, sscb);
}

//add a flag to set if localPort regist failed, just get a tempOne
int vroute::sendTo(int localPort, const EndPoint* target, int flag, const void* buffer, int bufferLen, int timeout){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->sendTo(localPort, target, flag, buffer, bufferLen, timeout, NULL);	
}

int vroute::sendTo_sync(int localPort, const EndPoint* target, int flag, const void* buffer, int bufferLen, sendToSyncCallback stscb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->sendTo(localPort, target, flag, buffer, bufferLen, -1, stscb);
}

int vroute::receiveFrom(int localPort, int flag, void* buffer, int bufferLen, int timeout){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->receiveFrom(localPort, flag, buffer, bufferLen, timeout, NULL);
}

int vroute::receiveFrom_sync(int localPort, receiveFromSyncCallback rfscb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->receiveFrom(localPort, 0, NULL, 0, -1, rfscb);
}

int vroute::connect(const EndPoint* target, int timeout, int localPort){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->connect(target, timeout, NULL, localPort);
}
	
int vroute::connect_sync(const EndPoint* target, connectCallback ccb, int localPort){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->connect(target, -1, ccb, localPort);
}

int vroute::getData(int port, char* buffer, int len){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->getData(port, buffer, len);
}

int vroute::getLocalAddr(NodeAddr* nodeAddr){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->getLocalAddr(nodeAddr);
}

int vroute::getRemoteAddr(vroute_t vid, NodeAddr* nodeAddr){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->getRemoteAddr(vid, nodeAddr);
}

//add a flag to use portPath path list intead of set as parameters
int vroute::tracertTarget(int port, int tracertType, const NodeAddr* target, NodeAddr* nodeList, int nodeCount, int timeout){	
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->tracertTarget(port, tracertType, target, nodeList, nodeCount, timeout, NULL);
}

int vroute::tracertTarget_sync(int port, int tracertType, const NodeAddr* target, tarcertTargetCallback ttcb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->tracertTarget(port, tracertType, target, NULL, 0, -1, ttcb);
}


int vroute::queryTarget(int port, int type, int valueLength, void* value, deviceInfo* result, int timeout){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->queryTarget(port, type, valueLength, value, result, timeout, NULL);
}

int vroute::queryTarget_sync(int port, int type, int valueLength, void* value, queryTargetCallback qtcb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->queryTarget(port, type, valueLength, value, NULL, -1, qtcb);
}


int vroute::targetReachAble(int port, const NodeAddr* target, int timeout){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->targetReachable(port, target, timeout, NULL);
}

int vroute::targetReachAble_sync(int port, const NodeAddr* target, targetReachAbleCallback tracb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->targetReachable(port, target, -1, tracb);
}

int vroute::setFixedNodeList(const NodeAddr* target, const NodeAddr* nodeList, int nodeCount){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->setFixedNodeList(target, nodeList, nodeCount);
}

int vroute::getVroutePort(vroute_t vid){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->getVroutePort(vid);
}

int vroute::getErrorInfo(int errno_num, char* buffer, int bufferLen){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->getErrorInfo(errno_num, buffer, bufferLen);
}

int vroute::isPortAlreadyExist(int port){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->isPortAlreadyExist(port);
}

int vroute::getAPort(int timeout){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->getAPort(timeout, NULL);
}
		
int vroute::getAPortSync(getPortCallback gcb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->getAPort(-1, gcb);
}
		
int vroute::registPort(int port, int timeout){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->registPort(port, timeout, NULL);
}

int vroute::registPortSync(int port, registPortCallback rgcb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->registPort(port, -1, rgcb);
}
		
int vroute::setPortClosingCallback(int port, portClosingCallback pccb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->setPortClosingCallback(port, pccb);
}

////////////////////////////////////////////////////////////////////
/// get a port closing event callback
///
/// parameters:
///		port: the target port to look for
///
/// return:
///		NULL: state not validate
///		portClosingCallback: the port closing callback
/////////////////////////////////////////////////////////////////////
portClosingCallback vroute::getPortClosingCallback(int port){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return NULL;
	}	
	return mPortManager->getPortClosingCallback(port);
}

////////////////////////////////////////////////////////////////////
/// set a port closing event callback
/// 
/// parameters:
///		vid: the vroute_t to set
///		pccb: the port closing callback
/// return:
///		E_TRANC_InsStateFailed: when the state invalidate
///		xxxxxx: return value from core
////////////////////////////////////////////////////////////////////
int vroute::setPortClosingCallbackVid(vroute_t vid, portClosingCallback pccb){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}	
	return mPortManager->setPortClosingCallbackVid(vid, pccb);
}

portClosingCallback vroute::getPortClosingCallbackVid(vroute_t vid){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){		
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return NULL;
	}	
	return mPortManager->getPortClosingCallbackVid(vid);
}

int vroute::close_vid(vroute_t vid){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}
	return mPortManager->closeVid(vid);
}

int vroute::close_port(int port){
	debug_enter();
	//check state
	if(mState != INS_STATE_OK){
		debug_record(logger::LEVEL_ERROR, "vroute class state error!!");
		return E_TRANC_InsStateFailed;
	}   
	return mPortManager->closePort(port);
}
